package com.FileBehavior;


import com.util.RandomKey;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;

public class FileIO {
    private static String ProjectPath = null;
    private static final String UploadFilesPath = getProjectPath() + "/UploadFiles/";

    private static final String DownloadFilesPath = getProjectPath() + "/Download/";

    public static String getDownloadFilesPath(){
        return DownloadFilesPath;
    }
    public static String getUploadFilesPath(){
        return UploadFilesPath;
    }

    public static File getFile(String filePath){
        File file = new File(filePath);
        if(!file.exists()){
            return null;
        }return file;
    }

    //上传文件，返回路径
    public static String saveFile(MultipartFile file, String fileName, boolean firstChunk){
        if(file.isEmpty()){
            return null;
        }
        // 上传文件夹的目录
        String path = getUploadFilesPath();
        File dir = new File(path);
        if(!dir.exists()){
            dir.mkdirs();
        }
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try{
            // 大文件分片上传合并
            // 新建一个文件，这时候内容是空的
            File localFile = new File(path + fileName);
            boolean append;
            if(firstChunk && localFile.exists()){
                // 第一个chunk， 而且存在了
                // 那就覆盖
                // no append
                append = false;
            }else{
                // append 追加到后面
                append = true;
            }
            File temp = File.createTempFile(path, "temp" + fileName);
            file.transferTo(temp);
            fis = new FileInputStream(temp);
            fos = new FileOutputStream(localFile, append);

            byte[] buf = new byte[1024];
            int len = 0;
            while(-1!=(len=fis.read(buf))){
                fos.write(buf);
            };
            fos.flush();
            fos.close();
            fos = null;
            fis.close();
            fis = null;
            temp.delete();
            return FileHelp.absoPathToRelaPath(path + fileName);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            try{
                if(fis!=null){
                    fis.close();
                }
                if(fos!=null){
                    fos.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static boolean delFile(String filePath){
        File temp = new File(filePath);
        if(!temp.exists()){
            return false;
        }
        // 删除文件
        temp.delete();
        return true;
    }


    public static void requestDownloadFile(String filePath, String fileName, HttpServletResponse response){
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        try {
            // 回复头
            // 跟上面的头不一样
            response.setHeader("content-type", "application/octet-stream");
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));

            // 转绝对路径
            filePath = FileHelp.relaPathToAbsoPath(filePath);
            fis = new FileInputStream(filePath);
            byte[] buffer = new byte[fis.available()];
            bis = new BufferedInputStream(fis);
            OutputStream os = response.getOutputStream();
            int i = bis.read(buffer);
            while(i != -1){
                os.write(buffer, 0, i);
                i = bis.read(buffer);
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try{
                if(bis != null){
                    bis.close();
                }
                if(fis != null){
                    fis.close();
                }
            }catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static String getProjectPath(){
        if(ProjectPath != null){
            return ProjectPath;
        }
        try {
            File directory = new File("");// 参数为空
            ProjectPath = directory.getCanonicalPath();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ProjectPath;
    }

    // RandomAccessFile分片
    public static String splitFile(String filePath){
        // https://blog.csdn.net/xuxile/article/details/90372302
        File file = new File(filePath);
        if(!file.exists()){
            return "";
        }
        RandomAccessFile in = null;
        RandomAccessFile out = null;
        long length = file.length();
        long splitSize = 4 * 1024 * 1024;//分片大小
        long count = (int)Math.ceil(length * 1.0 / splitSize);
        File dir = new File(filePath + ".part");
        if(dir.exists()){
            return dir.getAbsolutePath();
        }
        if(!dir.mkdir()){
            return "";
        }
        String fileName = file.getName();
        byte[] buf = new byte[1024];
        try {
            in = new RandomAccessFile(file, "r");
            for(int i = 0; i < count; i++){
                out = new RandomAccessFile(new File(dir.getAbsolutePath() + "/" + fileName + ".part" + i), "rw");
                long begin = i * splitSize;
                long end = begin + splitSize;
                int len = 0;
                in.seek(begin);
                // 当当前的指针没到最后，而且in还能读东西到buf中时
                while(in.getFilePointer() < end && -1!=(len= in.read(buf))){
                    out.write(buf, 0, len);
                }
                out.close();
                out=null;
            }
            in.close();
            in=null;
            //System.out.println("分片成功" + filePath);
        }
        catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            try{
                if(out!=null){
                    out.close();
                }if(in!=null){
                    in.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return dir.getAbsolutePath();
    }

    public static ArrayList<File> getOrderFileList(String fileDir){
        File dir = new File(fileDir);
        File[] files = dir.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                if(name.contains(".part")){
                    return true;
                }
                return false;
            }
        });
        if(files == null || files.length == 0){
            return new ArrayList<>();
        }
        List<File> fileList = Arrays.asList(files);
        fileList.sort(new Comparator<File>() {
            @Override
            public int compare(File o1, File o2) {
                String o1n = o1.getName();
                String o2n = o2.getName();
                int l1 = o1n.lastIndexOf(".part");
                int l2 = o2n.lastIndexOf(".part");
                String so1 = o1n.substring(l1 + 5);
                String so2 = o2n.substring(l2 + 5);
                int n1 = Integer.parseInt(so1);
                int n2 = Integer.parseInt(so2);
                return n1-n2;
            }
        });
        return new ArrayList<>(fileList);
    }

    public static void mergeFile(String newFilePath, String fileDir){
        ArrayList<File> fileList = getOrderFileList(fileDir);
        RandomAccessFile in = null;
        RandomAccessFile out = null;
        System.out.println("mergeFile");
        try{
            out = new RandomAccessFile(newFilePath, "rw");
            for(File file:fileList){
                in = new RandomAccessFile(file, "r");
                int len = 0;
                byte[] buf = new byte[1024];
                while(-1!=(len=in.read(buf))){
                    out.write(buf, 0, len);
                }
                in.close();
                in=null;
            }
            out.close();
            out=null;
            System.out.println("合并成功");
        } catch (IOException e) {
            System.out.println("合并失败");
            throw new RuntimeException(e);
        }finally {
            try{
                if(in!=null){
                    in.close();
                }
                if(out!=null){
                    out.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

}
